package mod_header

import (
	"ezcloud/gw/pkg/route"
	"net"
	"strings"
)

const (
	HeaderCloudIP       = "X-Cloud-Ip"
	HeaderForwardedHost = "X-Forwarded-Host"
	HeaderForwardedFor  = "X-Forwarded-For"
	HeaderForwardedPort = "X-Forwarded-Port"
	HeaderRealIp        = "X-Real-Ip"
)

func ModDefaultHeader(context *route.RouteContext, chain route.RouteFilterChain) {
	addForwardedAddr(context, chain)
	addRealIp(context, chain)
	addCloudIp(context, chain)
	chain.Filter(context)
}

func addForwardedAddr(context *route.RouteContext, chain route.RouteFilterChain) {
	// URL中Host和, Header中Host不同包含.
	if serverHost := context.OrigRequest.URL.Host; serverHost != "" {
		// serverHost >> host + ":" + port;
		if prior, existHost := context.OrigRequest.Header[HeaderForwardedHost]; existHost {
			serverHost = strings.Join(prior, ", ") + ", " + serverHost
		}
		context.RequestHeader.Set(HeaderForwardedHost, serverHost)
	}

	if clientIP, clientPort, err := net.SplitHostPort(context.OrigRequest.RemoteAddr); err == nil {
		if prior, existIP := context.OrigRequest.Header[HeaderForwardedFor]; existIP {
			clientIP = strings.Join(prior, ", ") + ", " + clientIP
		}
		context.RequestHeader.Set(HeaderForwardedFor, clientIP)

		if priorPort, existPort := context.OrigRequest.Header[HeaderForwardedPort]; existPort {
			clientPort = strings.Join(priorPort, ", ") + ", " + clientPort
		}
		context.RequestHeader.Set(HeaderForwardedPort, clientPort)
	}
}

func addCloudIp(context *route.RouteContext, chain route.RouteFilterChain) {
	t, ok := context.LocalAddr.(*net.TCPAddr)
	if ok {
		context.RequestHeader.Set(HeaderCloudIP, t.IP.String())
	}
}

func addRealIp(context *route.RouteContext, chain route.RouteFilterChain) {
	if _, ok := context.OrigRequest.Header[HeaderRealIp]; !ok {
		context.RequestHeader.Set(HeaderRealIp, context.OrigRequest.RemoteAddr)
	}
}
